/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xoskit.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#ifndef __8CD539A0_E036_4584_9B18_BED1095E41CB__
#define __8CD539A0_E036_4584_9B18_BED1095E41CB__

#include "../tools/head.h"
#include "include_odbc.h"
#include "err_info.h"
#include "i_stmt.h"

namespace xos_odbc
{

    class odbc_stmt : public xos_stl::mem_item< xos::release_impl< odbc_stmt >, thread_lock >,
        public i_stmt
    {
    public:
        typedef xos::release_impl< odbc_stmt > T;

    public:
        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // 
        static int get_xos_item_data( ITEM_DATA*& item_ptr );

    public:
        odbc_stmt();
        ~odbc_stmt();

    public:
        int bind_colum( int nCol, enumValueType eType, void * pBufByte, int nBufSize, intptr_t * StrLen_or_IndPtr );
        int bind_param( int nCol, enumDirection eType, enumValueType eValueType,
            enumValueType eParamType, int ColSize,
            int DecimalDigits,
            void * ParamValuePtr,
            int BufLen,
            intptr_t * StrLen_or_IndPtr );
        int bind_param( int nCol, const wchar_t * lpszData, int nNoop, intptr_t * StrLen_or_IndPtr );
        int bind_param( int nCol, int64_t * lpnData, intptr_t * StrLen_or_IndPtr );
        int bind_param( int nCol, int32_t * lpnData, intptr_t * StrLen_or_IndPtr );
        int bind_param( int nCol, int16_t * lpnData, intptr_t * StrLen_or_IndPtr );
        int bind_param( int nCol, int8_t * lpnData, intptr_t * StrLen_or_IndPtr );
        int bind_param( int nCol, uint64_t * lpnData, intptr_t * StrLen_or_IndPtr );
        int bind_param( int nCol, uint32_t * lpnData, intptr_t * StrLen_or_IndPtr );
        int bind_param( int nCol, uint16_t * lpnData, intptr_t * StrLen_or_IndPtr );
        int bind_param( int nCol, uint8_t * lpnData, intptr_t * StrLen_or_IndPtr );
        int bind_param( int nCol, bool * lpnData, intptr_t * StrLen_or_IndPtr );
        int bind_param( int nCol, float * lpfData, int nDigitNum, intptr_t * StrLen_or_IndPtr );
        int bind_param( int nCol, double * lpdData, int nDigitNum, intptr_t * StrLen_or_IndPtr );
        int bind_colum( int nCol, wchar_t * lpData, int nBufLen, intptr_t * StrLen_or_IndPtr );
        int bind_colum( int nCol, int64_t * lpData, intptr_t * StrLen_or_IndPtr );
        int bind_colum( int nCol, int32_t * lpData, intptr_t * StrLen_or_IndPtr );
        int bind_colum( int nCol, int16_t * lpData, intptr_t * StrLen_or_IndPtr );
        int bind_colum( int nCol, int8_t * lpData, intptr_t * StrLen_or_IndPtr );
        int bind_colum( int nCol, uint64_t * lpData, intptr_t * StrLen_or_IndPtr );
        int bind_colum( int nCol, uint32_t * lpData, intptr_t * StrLen_or_IndPtr );
        int bind_colum( int nCol, uint16_t * lpData, intptr_t * StrLen_or_IndPtr );
        int bind_colum( int nCol, uint8_t * lpData, intptr_t * StrLen_or_IndPtr );
        int bind_colum( int nCol, bool * lpData, intptr_t * StrLen_or_IndPtr );
        int bind_colum( int nCol, float * lpData, intptr_t * StrLen_or_IndPtr );
        int bind_colum( int nCol, double * lpData, intptr_t * StrLen_or_IndPtr );

        // 
        // 查询结果集中的列数,index从0开始
        // 
        int get_col_info( int nIndex, char * lpszName, int nLen, int & nType, int & nSize, int & nDigitNum, int & nCanNull );
        int get_affect_row_num( int & nNum );
        int get_row_num( int & nNum );
        int get_col_num( int & nNum );

        // 
        // 直接运行sql
        // 
        //  0 : success. 
        //  1 : running. 
        // -1 : failed
        // 
        int execute_direct( const char * lpszSql );

        //
        // 编译sql
        // 
        //  0 : success. 
        //  1 : running. 
        // -1 : failed
        // 
        int compile_sql( const char * lpszSql );

        // 
        // 绑定输入后执行sql语句写入
        // 
        //  0 : success. 
        //  1 : running. 
        // -1 : failed
        // 
        int execute();

        // 
        //  0 : success
        //  1 : pending
        //  2 : no data
        // -1 : failed
        // 
        int fetch();

    protected:
        // 
        // 翻译一下odbc返回的StrLen_or_IndPtr为i_stmt中的enumLenOrPtr类型
        // 
        int translate_strlen_or_indptr( intptr_t StrLen_or_IndPtr, intptr_t * lp_StrLen_or_IndPtr );
        int from_len_or_ptr( SQLLEN LenOrPtr, SQLLEN * lpLenOrPtr );
        int to_len_or_ptr( SQLLEN LenOrPtr, SQLLEN * lpLenOrPtr );
        int to_sql_io_type( int nInputType, int * lpnOutType );

        int from_sql_type( int nInputType, int * lpnOutType );
        int to_c_type( int nInputType, int * lpnOutType );

    public:
        int set_handle( SQLHANDLE hStmt );
        SQLHANDLE handle() const;
        int init();
        int term();

    private:
        int init_data();

    private:
        std::string m_sql;
        SQLHANDLE m_hStmt;
        err_info m_err;

    };

} // xos_odbc

#endif // __8CD539A0_E036_4584_9B18_BED1095E41CB__
